<?php

namespace App\Http\Controllers\Admin\Api;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Facades\ChargeRecordService;
use App\Facades\DeviceInfoService;
use App\Facades\DeviceService;
use App\Facades\UserService;
use App\Models\ChargeRecord;
use Cache;
use Carbon\Carbon;
use DB;

class DeviceController extends Controller
{
    public function recharge(Request $request)
    {
        
        $price = ChargeRecordService::getPrice();
        $rules = [
            'money' => 'required|integer|min:1',
            'flow' => 'required|integer|size:'.round($request->money/$price),
            'device_id' => 'required|exists:devices,id',
        ];
        $this->validate($request, $rules);

        $message = DB::transaction(function() use ($request, $price) {
            // 判断权限
            UserService::hasPermission(['superadmin']);
            // 拿到设备的device_id
            $deviceCode = DeviceService::getDeviceCodeByid($request->device_id);

            // 判断离线状态
            $status = DeviceService::isOffline($deviceCode, false)? ChargeRecord::ORDER_STATUS_OFFLINE_RECHARGE: ChargeRecord::ORDER_STATUS_PAID;

            // 判断需要增加充值额和剩余额的总值是否超过硬件程序可使用额的最大值。
            DeviceService::isExceedMaxRechargeAmount($deviceCode, $request->flow);
            
            // 添加充值记录
            $chargeRecord = ChargeRecordService::add($request->money, $request->flow, $request->device_id, $request->remark, $status, $price);
            // 充值成功后发送指令到设备
            if($status == ChargeRecord::ORDER_STATUS_PAID){
               DeviceService::control('recharge', $request->flow, $deviceCode, $chargeRecord->id, $chargeRecord->user_id);
            }
            // 返回信息
            return ($status == ChargeRecord::ORDER_STATUS_PAID)? '在线充值': '设备为离线状态。注意：请勿连续的、多次对同一设备进行离线充值';
        });
        // 
        return formatJsonResponse(null, $message);
    }

    public function reduce(Request $request)
    {
        $rules = [
            'charge_record_id' => 'required|exists:charge_records,id',
            'money' => 'required|integer|min:1',
            'flow' => 'required|integer',
            'device_id' => 'required|exists:devices,id',
            'remark' => 'required',
        ];
        $this->validate($request, $rules);
        
        DB::transaction(function() use ($request) {
            $user = UserService::hasPermission(['superadmin']);
            $chargeRecord = ChargeRecordService::updateChargeRecord($request->charge_record_id, ['status' => 3, 'discharge_admin_id' => $user->id, 'remark' => $request->remark, 'discharge_flow' => $request->flow, 'discharge_money' => $request->money], 2);
            $deviceCode = $chargeRecord->device->code;
            DeviceService::control('reduce_flow', $request->flow, $deviceCode, $chargeRecord->id);
        });
        return formatJsonResponse();
    }

    public function processFlowReminder(Request $request)
    {
        $rules = [
            'id' => 'required|exists:device_records,id',
            'flow_status' => 'required|boolean',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        $reminders = DeviceService::update($request->only(['id']), $request->only(['flow_status']));
        $count = DeviceService::countFlowRemindListByStatus(0);
        return formatJsonResponse(['count' => $count]);
    }

    public function processFilterReminder(Request $request)
    {
        $rules = [
            'id' => 'required|exists:device_records,id',
            'filter_status' => 'required|boolean',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        $reminders = DeviceService::update($request->only(['id']), $request->only(['filter_status']));
        $count = DeviceService::countFilterRemindListByStatus(0);
        return formatJsonResponse(['count' => $count]);
    }

    public function addInstallInfo(Request $request)
    {
        $rules = [
            'device_code' => 'required|digits:16',
            'customer_name' => 'required',
            'phone' => 'required|telephone',
            'installation_address' => 'required',
            'operator' => 'required',
            'operator_phone' => 'required|telephone',
            'status' => 'required|in:未安装,已安装',
            'dealer' => 'required',
            'install_at' => 'required|date_format:Y-m-d|after:2000-01-01',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        $installAt = Carbon::createFromFormat('Y-m-d', $request->install_at);
        DeviceInfoService::addInstallInfo(array_merge($request->only([
                                                            'device_code',
                                                            'customer_name',
                                                            'phone',
                                                            'installation_address',
                                                            'operator',
                                                            'operator_phone',
                                                            'status',
                                                            'dealer',
                                                            'install_at',
                                                            'remark',
                                                        ]), ['install_at' => $installAt]));
        return formatJsonResponse();
    }

    public function updateInstallInfo(Request $request)
    {
        $rules = [
            'id' => 'required|exists:install_infos,id',
            'device_code' => 'required|digits:16|unique:install_infos,device_code,'.$request->id,
            'customer_name' => 'required',
            'phone' => 'required|telephone',
            'installation_address' => 'required',
            'operator' => 'required',
            'operator_phone' => 'required|telephone',
            'status' => 'required|in:未安装,已安装',
            'dealer' => 'required',
            'install_at' => 'required|date_format:Y-m-d|after:2000-01-01',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        $installAt = Carbon::createFromFormat('Y-m-d', $request->install_at);
        DeviceInfoService::updateInstallInfo($request->id, array_merge($request->only([
                                                            'device_code',
                                                            'customer_name',
                                                            'phone',
                                                            'installation_address',
                                                            'operator',
                                                            'operator_phone',
                                                            'status',
                                                            'dealer',
                                                            'install_at',
                                                            'remark',
                                                        ]), ['install_at' => $installAt]));
        return formatJsonResponse();
    }

    public function deleteInstallInfo(Request $request)
    {
        $rules = [
            'id' => 'required|exists:install_infos,id',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        DeviceInfoService::deleteInstallInfo($request->id);
        return formatJsonResponse();
    }

    public function addMaintainInfo(Request $request)
    {
        $rules = [
            'device_code' => 'digits:16',
            'customer_name' => 'required',
            'phone' => 'required|telephone',
            'installation_address' => 'required',
            'charge' => 'numeric',
            'operator_phone' => 'telephone',
            'maintain_at' => 'date_format:Y-m-d|after:2000-01-01',
            'reserve_at' => 'required|date_format:Y-m-d H|after:2000-01-01 0',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        DeviceInfoService::addMaintainInfo($request->only([
                'device_code',
                'customer_name',
                'phone',
                'installation_address',
                'charge',
                'operator',
                'operator_phone',
                'component',
                'remark',
                'reserve_at',
                'maintain_at']));
        return formatJsonResponse();
    }

    public function updateMaintainInfo(Request $request)
    {
        $rules = [
            'id' => 'required|exists:maintain_infos,id',
            'device_code' => 'required|digits:16',
            'customer_name' => 'required',
            'phone' => 'required|telephone',
            'installation_address' => 'required',
            'charge' => 'required|numeric',
            'operator' => 'required',
            'operator_phone' => 'required|telephone',
            'component' => 'required',
            'maintain_at' => 'required|date_format:Y-m-d|after:2000-01-01',
            'reserve_at' => 'required|date_format:Y-m-d H|after:2000-01-01 0',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        DeviceInfoService::updateMaintainInfo($request->id, $request->only([
                'device_code',
                'customer_name',
                'phone',
                'installation_address',
                'charge',
                'operator',
                'operator_phone',
                'component',
                'remark',
                'reserve_at',
                'maintain_at']));
        return formatJsonResponse();
    }

    public function getMaintainInfoById(Request $request)
    {
        $rules = [
            'id' => 'required|exists:maintain_infos,id',
        ];
        $this->validate($request, $rules);

        return formatJsonResponse(DeviceInfoService::getMaintainInfoById($request->id));
    }

    public function deleteMaintainInfo(Request $request)
    {
        $rules = [
            'id' => 'required|exists:maintain_infos,id',
        ];
        $this->validate($request, $rules);

        UserService::hasPermission(['admin']);
        DeviceInfoService::deleteMaintainInfo($request->id);
        return formatJsonResponse();
    }

    public function halt(Request $request)
    {
        $rules = [
            'command' => 'required|in:halt,stop_halt',
            'device_code' => 'required|exists:devices,code',
        ];
        $this->validate($request, $rules);
        
        $user = UserService::hasPermission(['finance']);
        DeviceService::control($request->command, $request->num, $request->device_code, null,$user->id);
        return formatJsonResponse();
    }

    public function processMaintainInfo(Request $request)
    {
        $rules = [
            'id' => 'required|exists:maintain_infos,id',
            'status' => 'required|in:1',
        ];
        $this->validate($request, $rules);

        $user = UserService::hasPermission(['admin']);
        DeviceInfoService::updateMaintainInfo($request->id, $request->only(['status']));
        $count = DeviceService::countmaintainInfoListByStatus(0);
        return formatJsonResponse(['count' => $count]);
    }

    public function getInstallAddressByDeviceCode(Request $request)
    {
        $rules = [
            'device_code' => 'required|exists:install_infos,device_code',
        ];
        $this->validate($request, $rules);

        $installAddress = DeviceService::getInstallAddressByDeviceCode($request->device_code);
        return formatJsonResponse(['install_address' => $installAddress]);
    }

    public function formatCondition($condition)
    {
        $condition = str_replace('%', '\%', $condition);
        $condition = str_replace('_', '\_', $condition);
        return $condition;
    }

    public function getInstallerByQuery(Request $request)
    {
        $condition = $this->formatCondition($request->condition);
        return formatJsonResponse(DeviceService::getInstallerByQueryColumn($condition));
    }

    public function getDealerByQuery(Request $request)
    {
        $condition = $this->formatCondition($request->condition);
        return formatJsonResponse(DeviceService::getDealerByQueryColumn($condition));
    }

    public function setDischargeMoney()
    {
        $user = UserService::hasPermission(['admin']);
        ChargeRecordService::setDischargeMoneyAndMoney();
        return formatJsonResponse();
    }

    public function modeRecharge(Request $request)
    {
        // 单价
        /*
        device_id:18
        mode:2
        money:20
        quantity:20
        */
        $price = ChargeRecordService::getPrice();

        $rules = [
            'mode' => 'required',
            'money' => 'required_if:mode,2|integer|min:1',
            'device_id' => 'required|exists:devices,id',
        ];

        if($request->mode == 1){
            $rules = array_merge($rules, ['quantity' => 'required|integer|min:1']);
        }else{
            $rules = array_merge($rules, ['quantity' => 'required|integer|size:'.round($request->money/$price)]);
        }
        $this->validate($request, $rules);

        // 事务处理 返回闭包值，将数据存储到了数据库中
        $message = DB::transaction(function() use ($request, $price) {
            // 判断superadmin是否有权限
            UserService::hasPermission(['superadmin']);

            //根据设备关联ID查出设备编号
            $deviceCode = DeviceService::getDeviceCodeByid($request->device_id);

            // 确认设备状态
            $device_status = DeviceService::isExceedMaxRechargeAmount($deviceCode, $request->quantity, $request->mode);

            if(substr($deviceCode, 0, 2) == '21'){
                $status = DeviceService::isOffline($deviceCode, false)? ChargeRecord::ORDER_STATUS_OFFLINE_RECHARGE: ChargeRecord::ORDER_STATUS_PAID;

                $chargeRecord = ChargeRecordService::add($request->money, $request->quantity, $request->device_id, $request->remark, $status, $price, $request->only(['mode']));
                if($status == ChargeRecord::ORDER_STATUS_PAID){
                    $quantity = ($request->mode == 1)? (($request->quantity)*24*60*60): $request->quantity;
                    DeviceService::control('mode_recharge', $quantity, $deviceCode, $chargeRecord->id, $chargeRecord->user_id, true, $request->mode);
                }
                return ($status == ChargeRecord::ORDER_STATUS_PAID)? '在线充值': '设备为离线状态。注意：请勿连续的、多次对同一设备进行离线充值';
            }else{
                return '设备充值失败：旧版本程序';
            }
        });

        return formatJsonResponse(null, $message);
    }

    public function modeReduce(Request $request)
    {
        $rules = [
            'mode' => 'required',
            'quantity' => 'required|integer|min:1',
            'charge_record_id' => 'required|exists:charge_records,id',
            'money' => 'required_if:mode,2|integer|min:1',
            'device_id' => 'required|exists:devices,id',
            'remark' => 'required',
        ];
        $this->validate($request, $rules);
        
        DB::transaction(function() use ($request) {
            $user = UserService::hasPermission(['superadmin']);
            $updateData = [
                'status' => 3,
                'discharge_admin_id' => $user->id,
                'remark' => $request->remark,
                'discharge_money' => $request->money,
                'mode' => $request->mode,
            ];
            if($request->mode == 1){
                $updateData = array_merge($updateData, ['discharge_time' => $request->quantity]);
                $quantity = ($request->quantity) * 60* 60* 24;
            }else{
                $updateData = array_merge($updateData, ['discharge_flow' => $request->quantity]);
                $quantity = $request->quantity;
            }
            $chargeRecord = ChargeRecordService::updateChargeRecord($request->charge_record_id, $updateData, $request->mode);
            $deviceCode = $chargeRecord->device->code;
            DeviceService::control('mode_reduce', $quantity, $deviceCode, $chargeRecord->id, null, true, $request->mode);
        });
        return formatJsonResponse();
    }
}
